
#include "gfs_api.h"

#ifdef GTREE_FILE_COURCE

static HANDLE spi_mt_tag = NULL;
#define	FLS_MUTEX_CREAT()		spi_mt_tag=CreateSemaphoreA(NULL, 1, 1, "FlsMutex")
#define	FLS_MUTEX_DELETE()		CloseHandle(spi_mt_tag)
#define	FLS_MUTEX_LOCK()		WaitForSingleObject(spi_mt_tag,INFINITE)
#define	FLS_MUTEX_UNLOCK()		ReleaseSemaphore(spi_mt_tag, 1, NULL)

#ifdef GTREE_FILE_ERR_RECORD
u32	SaveDataErr=0,SaveHearErr=0,SaveGlobalErr=0;
u32 gfs_erase_times=0,gfs_erase_Global=0;
#endif

#define TEST_FLASH_SIZE FLASH_TOTAL_SIZE
static u8* pFlashStartAddr = NULL;
static u8 Flashstatus[FLASH_TOTAL_SIZE/FLASH_SECTOR_SIZE];		//E=0,r |= 0x01, w |= 0x02
static u16 FlashOffset[FLASH_TOTAL_SIZE/FLASH_SECTOR_SIZE];		//last offset 

extern void* APP_fileRead(char* pFileName, int* pOutLen);
extern void APP_fileSave(char* pFileName, void* pInBuff, int Inlen);
int SPI_Flash_init(void)
{
	int ret=-1;
	if (pFlashStartAddr==NULL) {
		int OutLen;
		pFlashStartAddr=(u8*)APP_fileRead("gFsData.bin",&OutLen);
		if(pFlashStartAddr==NULL) {
			LG("Flash_init->pFlashStartAddr Is NULL");
			pFlashStartAddr = (u8*)malloc(TEST_FLASH_SIZE);
			memset_u32((u32*)pFlashStartAddr,0xffffffff, TEST_FLASH_SIZE/sizeof(u32));
			ret= 1;
		}
		else {
			ret= 0;
		}
		FLS_MUTEX_CREAT();
	}
	memset(Flashstatus,0x00,sizeof(Flashstatus));
	memset(FlashOffset,0x00,sizeof(FlashOffset));
	
	LG("Flash_init[%d,%d,%d],DfgFsUnitHead[%d],DfgFsUnitBlock[%d]",GFS_BIT_FLAG,GFS_FILE_MAX,sizeof(DfGTreeFsGlobal),
		sizeof(DfgFsUnitHead),sizeof(DfgFsUnitBlock));
	#ifdef GFS_RECORD_FUNTION
	LG("->DfgRcUnitHead[%d]DfgRcUnitBlock[%d]", sizeof(DfgRcUnitHead), sizeof(DfgRcUnitBlock));
	#endif
	//TRACE_HEX("FLASH_4M",pFlashStartAddr+(4*256)*4096,128);
	return ret;
}

int SPI_Flash_ERASE_ALL()
{
	if (pFlashStartAddr) {
		memset(pFlashStartAddr, 0xff, TEST_FLASH_SIZE);
	}
}

int SPI_Flash_Deinit(void)
{
	if (pFlashStartAddr) {
		APP_fileSave("gFsData.bin",pFlashStartAddr,TEST_FLASH_SIZE);
		free(pFlashStartAddr);
		pFlashStartAddr=NULL;
		FLS_MUTEX_DELETE();
	}
	LG("Flash_Deinit ->gFsData.bin");
	return 0;
}


int SPI_Flash_Exist(void)
{
	if (pFlashStartAddr == NULL) return -1;
	return 0;
}




void SPI_Flash_ERASE_One(u32 addr)
{
	addr -= FLASH_TOTAL_START;
	addr &= (~(FLASH_SECTOR_SIZE - 1));
	memset_u32((u32*)(pFlashStartAddr + addr), 0xffffffff, FLASH_SECTOR_SIZE /sizeof(u32));
	Flashstatus[(addr)/ FLASH_SECTOR_SIZE] = 0;
	FlashOffset[(addr)/ FLASH_SECTOR_SIZE] = 0;
	#ifdef GTREE_FILE_ERR_RECORD
	gfs_erase_times++;
	#endif
}

int SPI_Flash_Read(u32 addr, void* buff, int size)
{
	if((addr >= FLASH_TOTAL_SIZE) || (NULL == buff) || (size <=0)) {
    	SZ_LOG(LOG_ERROR,"###Flash_Read[%X][%d] Err\r\n",addr,size);
        return -1;
    }
	addr -= FLASH_TOTAL_START;
	FLS_MUTEX_LOCK();
	memcpy(buff, pFlashStartAddr + addr, size);
	for(int j=0;j<size;j++) {
		Flashstatus[(addr+j)/ FLASH_SECTOR_SIZE] |= 0x01;
		j += FLASH_SECTOR_SIZE;
	}
	FLS_MUTEX_UNLOCK();
	return size;
}

int SPI_Flash_Write(u32 addr, void* buff, int Len)
{
	if((addr >= FLASH_TOTAL_SIZE) || (Len == 0)) {
    	SZ_LOG(LOG_ERROR,"###Flash_Write[%X] [%d]Err\r\n",addr,Len);
        return -1;
    }	
	addr -= FLASH_TOTAL_START;
	int i,index;
	FLS_MUTEX_LOCK();
	for(i=0; i<Len; i++)
		pFlashStartAddr[addr+i] &= ((u8*)buff)[i];
	
	for(i=0; i<Len; i++) {
		if(pFlashStartAddr[addr+i] != ((u8*)buff)[i])
			break;
	}
	if(i<Len) {
		index = (addr+i)/ FLASH_SECTOR_SIZE;
		#ifdef GTREE_FILE_ERR_RECORD
		SaveDataErr++;
		#endif
		SZ_LOG(LOG_ERROR,"###CheckWrite[%d.%d]i[%d] flag[%d] offset[%d]\r\n",addr/ FLASH_SECTOR_SIZE,addr&(FLASH_SECTOR_SIZE -1),i,Flashstatus[index],FlashOffset[index]);
	}
	for(i=0;i<Len;i++) {
		index = (addr+i)/ FLASH_SECTOR_SIZE;
		Flashstatus[index] |= 0x02;
		FlashOffset[index]=(Len-i)>= FLASH_SECTOR_SIZE ? FLASH_SECTOR_SIZE :((addr+Len)&(FLASH_SECTOR_SIZE -1));
		i += FLASH_SECTOR_SIZE;
	}
	FLS_MUTEX_UNLOCK();
	return Len;
}

int SPI_Flash_ERASE_SECTOR(u32 addr)
{
	if(addr >= FLASH_TOTAL_SIZE) {
    	SZ_LOG(LOG_ERROR,"###Flash_ERASE_SECTOR[%X] Err\r\n",addr);
        return -1;
    }
	FLS_MUTEX_LOCK();
	SPI_Flash_ERASE_One(addr);
	FLS_MUTEX_UNLOCK();
	return 0;
}

int SPI_Flash_ERASE_16Block(u32 addr)	// 64k SPI_BLOCK_SIZE
{
	addr &= ~((16* FLASH_SECTOR_SIZE) - 1);
	FLS_MUTEX_LOCK();
	for(int i=0;i<16;i++) {
		SPI_Flash_ERASE_SECTOR(addr);
		addr += FLASH_SECTOR_SIZE;
	}
	FLS_MUTEX_UNLOCK();
	return 0;
}


#endif


